home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr22
/
byte24.zip
/
BENCHCOD.C
< prev
next >
Wrap
Text File
|
1993-04-14
|
41KB
|
1,587 lines
/*«PL1»*/
/*
** Low-level Benchmarks for 80x86 machines.
** BYTE Magazine
** Apr. 1990
**
** This module contains the high level source for the BYTE benchmarks
** Routines called from this module may be found in BENCHSUBS.ASM.
**
** VERSION 2.3 -- This code corrected so that iteration counts are
** now long integers. -- RG
**
*/
#include <stdio.h>
#include <stdarg.h>
#include <dos.h>
#include <mem.h>
#include <math.h>
#include <float.h>
#include "benchdef.h"
#include "win.h"
/* Typedefs */
typedef struct {
unsigned int maxhead; /* Max head number */
unsigned int maxcyl; /* Max cylinder number */
unsigned int sectspertrack; /* Sectors per track */
} harddiskspecs;
/* external globals */
extern unsigned long ll_filelen();
extern volatile struct mcfig machine_config;
extern int tdef[14];
extern int oldlen;
/* window prototypes (winsubs.asm)*/
extern int chattr (win_handle *, int, int, int, int, int, int);
extern int winputch (win_handle *, int, int, char);
extern void clearscreen (void);
/* misc prototypes (miscsubs.asm) */
extern void click(void);
/*local prototypes */
char *gfname(int);
long randwc(long);
long randnum(long);
double timetodouble( unsigned int *);
void adjust_bar(win_handle*, int, int);
/****************************
* sieve *
*****************************
** The (in)famous sieve of Eratosthenes.
** Call with:
** sieve (winptr,dotime,acttime,iters)
** Where:
** winptr= handle of window upon which to draw slidey-bar; null means don't
** dotime = # of seconds for the system to execute the sieve
** Returns:
** acttime[3] = pointer to a 3-element array
** acttime[0] = # of microseconds actually elapsed
** acttime[1] = # of milliseconds actually elapsed
** acttime[2] = # of seconds actually elapsed
** iters = number of iterations performed in acttime
*/
sieve(winptr,dotime,acttime,iters)
win_handle *winptr; /* current window */
unsigned int dotime; /* Seconds to execute */
unsigned int acttime[3]; /* Actual elapsed time */
unsigned long *iters; /* # of iterations performed */
{
unsigned int mysegptr; /* Place to hold pointer for segment */
unsigned int mytime[3]; /* Local for time accumulation */
/* Clear # of iterations and actual time */
*iters=0L;
acttime[0]=acttime[1]=acttime[2]=0;
/* Get a segment for the array */
if(allocmem(SIEVESIZE/16+1,&mysegptr)!=-1)
return; /* Allocation failed */
/* Loop and execute */
do {
start_timer();
/*
** NOTE: If you want to see how many primes the do_sieve() function
** finds, simply examine its return value. We don't do that here.
**
** 4/14/93 - Modified so that sieve performs 25 iterations per
** call. RG
*/
do_sieve(mysegptr,SIEVESIZE);
stop_timer(mytime);
/* Accumulate elapsed time into total time */
accumtime(mytime,acttime);
*iters+=25L; /* 4/14/93 25 iters per!! */
if(winptr!=NULL)
adjust_bar(winptr, acttime[2], dotime); /* slide the bar */
} while(acttime[2]<dotime);
/* Free the array segment */
freemem(mysegptr);
}
/****************************
* sort *
*****************************
** The Sort benchmark (new and improved!)
** Call with:
** sort(winptr,dotime,acttime,iters)
** Where:
** winptr= handle of window upon which to draw slidey-bar; null means don't
** dotime = # of seconds to perform the sort
** Returns:
** acttime[3] = pointer to a 3-element array
** acttime[0]=# of microseconds elapsed
** acttime[1]=# of milliseconds elapsed
** acttime[2]=# of seconds elapsed
** iters = # of iterations completed
**
** NOTE: Here, a SINGLE iteration is considered to be 1 pass
** of the quick sort and 1 pass of the shell sort.
*/
sort(winptr, dotime,acttime,iters)
win_handle *winptr; /* current window */
unsigned int dotime; /* Time to do iterations */
unsigned int acttime[3]; /* Actual elapsed time */
unsigned long *iters; /* # of iterations */
{
unsigned int mysegptr; /* Pointer to array segment */
unsigned int mytime[3]; /* Local for elapsed time */
unsigned int rarrayseg; /* Pointer to random array */
/* Clear iterations and actual time */
*iters=0L;
acttime[0]=acttime[1]=acttime[2]=0;
/* Allocate memory segments for the arrays */
if(allocmem(SORTSIZE/8+1,&mysegptr)!=-1)
return; /* Return if failure */
if(allocmem(SORTSIZE/8+1,&rarrayseg)!=-1)
{ freemem(mysegptr);
return; /* Return if failure */
}
/* Restart the random number generator */
randnum(1L);
/* Fill up the random array */
rload_int_seg(rarrayseg,SORTSIZE,32767);
do {
/* Copy random array into local */
segcopy(mysegptr,rarrayseg,SORTSIZE+SORTSIZE);
start_timer();
/* Do a quicksort */
do_qsort(mysegptr,0,SORTSIZE);
stop_timer(mytime);
accumtime(mytime,acttime);
/* Fill the array again */
segcopy(mysegptr,rarrayseg,SORTSIZE+SORTSIZE);
start_timer();
/* Do a shellsort */
do_shell(mysegptr,SORTSIZE);
stop_timer(mytime);
accumtime(mytime,acttime);
*iters+=1L; /* Increment iterations counter */
if(winptr!=NULL)
adjust_bar(winptr, acttime[2], dotime); /* slide the bar */
} while(acttime[2]<dotime);
/* Free the memory segments */
freemem(rarrayseg);
freemem(mysegptr);
}
/****************************
* movetest *
*****************************
** Executes the string move benchmarks.
** Call with:
** dotime = max # of seconds for each test
** nk = # of K bytes to move
** Returns:
** acttime[5][3] = Matrix of results. First index picks:
** 0=byte-wide
** 1=word-wide, odd address
** 2=word-wide, even address
** 3=dword-wide, odd address
** 4=dword-wide, even address
** The last two are filled only if is386!=0.
** Second index picks 0=micr, 1=milli, 2=seconds.
** iters[5] = # of iterations for each test.
*/
movetest(winptr, dotime,nk,acttime,iters)
win_handle *winptr; /* current window */
unsigned int dotime; /* Time to run each test */
unsigned int nk; /* K bytes to move */
unsigned int acttime[5][3]; /* Actual elapsed time */
unsigned long iters[5]; /* Iterations for each test */
{
unsigned int ssegptr; /* Source segment */
unsigned int dsegptr; /* Destination segment */
unsigned int i,j; /* Index variables */
unsigned int totloops; /* processor dependent number of loops */
/* Clear out the results arrays */
for(i=0;i<5;i++)
{ iters[i]=0L;
for(j=0;j<3;j++)
acttime[i][j]=0;
}
/* Allocate source and destination segments */
if(allocmem(nk*64+1,&ssegptr)!=-1) return;
if(allocmem(nk*64+1,&dsegptr)!=-1)
{ freemem(ssegptr);
return;
}
/* Loop through the tests */
/* Can we do 386 stuff? */
totloops=(machine_config.proc_type>286)? 5:3;
for(i=0; i<totloops; ++i)
{
moveloop(i,ssegptr,dsegptr,nk,dotime,acttime,iters);
if(winptr!=NULL)
adjust_bar(winptr, i+1, totloops); /* slide the bar */
}
/* Free up segments */
freemem(dsegptr);
freemem(ssegptr);
return;
}
/****************************
* moveloop *
*****************************
* Inner loop of movetest
* i selects which test:
* 0 = byte wide
* 1 = word wide odd boundary
* 2 = word wide even boundary
* 3 = double word wide odd boundary
* 4 = double word wide even boundary
*/
moveloop(i,seg1,seg2,nk,dotime,acttime,iters)
unsigned int i; /* Which test to perform */
unsigned int seg1; /* Segment 1 (source) */
unsigned int seg2; /* Segment 2 (destination) */
unsigned int nk; /* Number of K bytes */
unsigned int dotime; /* Max seconds to do */
unsigned int acttime[5][3]; /* Actual elapsed time */
unsigned long iters[5]; /* Iterations */
{
unsigned int nb; /* Number of bytes to move */
unsigned int nw; /* Number of words to move */
unsigned int nd; /* Number of doublewords to move */
unsigned int soff; /* Source offset */
unsigned int doff; /* Destination offset */
unsigned int myactime[3]; /* Local for accumulating time */
unsigned int eltime[3]; /* Local for elapsed time per iteration */
/* Clear accumulators */
myactime[0]=myactime[1]=myactime[2]=0;
/* Set bytes, words, and doublewords */
nb=nk*1024; /* Calc number of bytes */
nw=nb>>1; /* Calc number of words */
nd=nw>>1; /* Calc number of dwords */
/* Set even/odd boundary */
soff=doff=0;
if((i&1)!=0) soff=doff=1;
do {
/*
** The i variable tells us which test to perform.
** 4/14/93 Each move operations performs 25 iterations RG
*/
switch(i) {
case 0: /* Byte wide */
start_timer();
do_bmove(seg1,soff,seg2,doff,nb);
stop_timer(eltime);
break;
case 1: /* Word wide odd */
case 2: /* Word wide even */
start_timer();
do_wmove(seg1,soff,seg2,doff,nw);
stop_timer(eltime);
break;
case 3: /* Dword wide odd */
case 4: /* Dword wide even */
start_timer();
do_dmove(seg1,soff,seg2,doff,nd);
stop_timer(eltime);
break;
default:
break;
} /* End of switch */
accumtime(eltime,myactime);
iters[i]+=25L; /* 25 iterations!! */
} while(myactime[2]<dotime);
acttime[i][0]=myactime[0]; acttime[i][1]=myactime[1];
acttime[i][2]=myactime[2];
return;
}
/****************************
* ifourbang *
*****************************
** Integer math tests.
** Note, n indicates the number of times each 4 operations
** (add, subtract, multiply, and divide) are performed.
** Maximum is 8192.
*/
ifourbang(winptr, dotime, n, acttime,iters)
win_handle *winptr; /* current window handlke */
unsigned int dotime; /* Seconds to perform operations */
unsigned int n; /* number of operations */
unsigned int acttime[3]; /* Actual elapsed time */
unsigned long *iters; /* Iterations completed */
{
unsigned int i; /* Index */
unsigned int rn; /* Random number */
unsigned int mysegptr; /* Pointer to working segment */
unsigned int huge *isegptr; /* Actual pointer to rands */
unsigned int mytime[3]; /* Local for elapsed time */
/* Clear iterations and actual time */
*iters=0;
acttime[0]=acttime[1]=acttime[2]=0;
/* Allocate memory segments for the arrays */
if(allocmem(n/2,&mysegptr)!=-1)
return; /* Return if failure */
/* Build the random array */
isegptr=MK_FP(mysegptr,0);
i=0;
do {
if(i==0) *(isegptr+i)=2;
else *(isegptr+i)=*(isegptr+i-1)+1;
++i;
*(isegptr+i)=*(isegptr+i-1)-1; ++i;
*(isegptr+i)=*(isegptr+i-1)+2; ++i;
*(isegptr+i)=*(isegptr+i-1)-1; ++i;
} while(i<(n*4));
do {
start_timer();
/*
** 4/14/93 Each ifourbang() call performs 10 iterations RG
*/
do_ifourbang(mysegptr,n);
stop_timer(mytime);
accumtime(mytime,acttime);
*iters+=10L;
if(winptr!=NULL)
adjust_bar(winptr, acttime[2], dotime); /* slide the bar */
}while(acttime[2]<dotime);
/* Free memory segments */
freemem(mysegptr);
}
/****************************
* ffourbang *
*****************************
** Floating-point version of ifourbang.
*/
ffourbang(winptr,dotime,acttime,iters)
win_handle *winptr; /* current window handle */
unsigned int dotime; /* # of seconds to do the test */
unsigned int acttime[3]; /* Actual elapsed time */
unsigned long *iters; /* # of iterations */
{
unsigned int mytime[3]; /* Local for elapsed time */
/* Clear iterations and actual time */
*iters=0L;
acttime[0]=acttime[1]=acttime[2]=0;
do {
start_timer();
do_fourbang(FFITERS);
stop_timer(mytime);
accumtime(mytime,acttime);
*iters+=1L;
if(winptr!=NULL)
adjust_bar(winptr, acttime[2], dotime); /* slide the bar */
} while(acttime[2]<dotime);
}
/****************************
* fourier *
*****************************
** Calculates fourier coefficients for a square wave.
*/
fourier(winptr, dotime,acttime,iters)
win_handle *winptr; /* current window handle */
unsigned int dotime; /* Time to do test */
unsigned int acttime[3]; /* Actual elapsed time */
unsigned long *iters; /* Iterations */
{
double coeffs[NCOEFFS*2]; /* Coefficients array */
unsigned int mytime[3]; /* Local time */
/* Clear iterations and actual time */
*iters=0L;
acttime[0]=acttime[1]=acttime[2]=0;
do{
start_timer();
/*
** 4/14/93 Each square_fourier() call performs 25 iterations RG
*/
square_fourier(NCOEFFS,coeffs);
stop_timer(mytime);
accumtime(mytime,acttime);
*iters+=25L;
if(winptr!=NULL)
adjust_bar(winptr, acttime[2], dotime); /* slide the bar */
} while(acttime[2]<dotime);
}
/****************************
* textbench *
*****************************
** Random text display benchmark (cursor positioning)
** This routine tests appropriate modes.
*/
textbench(dotime,n,avgips)
unsigned int dotime; /* # of seconds to do the test */
unsigned int n; /* # of characters to display */
double *avgips; /* average iterations per second */
{
/* Maximum column # */
unsigned int acttime[3][3]; /* Actual elapsed time */
unsigned long iters[3]; /* Iterations */
unsigned int cmax[3]={80,80,80};
unsigned int modes[3]={2,3,7};
unsigned int nummodes;
unsigned int vpage; /* Video page segment */
unsigned int rcseg; /* Row/column segment number */
unsigned int attseg; /* Attributes segment */
int i,j; /* Indices */
unsigned char far *attsegptr; /* Far pointer to attribute seg */
unsigned int mytime[3]; /* Local for elapsed time */
/* just for looks */
clearscreen();
printf("Preparing text benchmarks ...");
/* set modes according to type */
switch(machine_config.graphics_type){
case MDA:
case HERC:
nummodes=1;
modes[0]=7;
break;
case CGA:
nummodes=2;
break;
case EGAM:
case EGAC:
case VGA:
nummodes=3;
break;
}
/* Clear all the accumulators */
for(i=0;i<3;i++)
{ iters[i]=0L;
for(j=0;j<3;j++)
acttime[i][j]=0;
}
/* Allocate the row/column and attributes segments */
if(allocmem(n/8+1,&rcseg)!=-1)
return;
if(allocmem(n/16+1,&attseg)!=-1)
{ freemem(rcseg);
return;
}
/* Restart the random number generator */
randnum(1L);
/* Fill the attributes segment */
attsegptr=MK_FP(attseg,0);
for(i=0;i<n;i++)
*(attsegptr+i)=(unsigned char)randwc(256L);
/* Loop through the tests */
clearscreen();
for(i=0;i<nummodes;i++)
{ textbloop(dotime,n,mytime,&iters[i],modes[i],cmax[i],rcseg,attseg);
acttime[i][0]=mytime[0];
acttime[i][1]=mytime[1];
acttime[i][2]=mytime[2];
}
/* Clean up after yourself */
freemem(attseg);
freemem(rcseg);
/* calculate avgips */
*avgips=0;
for(i=0;i<nummodes;i++){
*(avgips)+=((double)iters[i])/timetodouble(acttime[i]);
}
*avgips/=nummodes;
return;
}
/****************************
* textbloop *
*****************************
** Inner loop for the random text benchmark.
*/
textbloop(dotime,n,acttime,iters,vmode,cmax,rcseg,attseg)
unsigned int dotime; /* Max seconds to execute */
unsigned int n; /* Number of entries */
unsigned int acttime[3]; /* Actual time */
unsigned long *iters; /* Iterations */
unsigned int vmode; /* Graphics mode */
unsigned int cmax; /* Column max */
unsigned int rcseg; /* Row/column segment */
unsigned int attseg; /* Attributes segment */
{
unsigned int vpage; /* Video page segment */
unsigned int far *rcsptr; /* Pointer to row/col segment */
unsigned int eltime[3]; /* Holding for elapsed time */
unsigned int i; /* Index */
unsigned int myvmode; /* Saved video mode */
/* just for looks */
printf("Running random text benchmark ...");
/* Build far pointer */
rcsptr=MK_FP(rcseg,0);
/* Fill up the row/column segment */
for(i=0;i<n;i++)
{ *(rcsptr+i)=(unsigned int)(abs((randwc(25L)<<8))+
abs(randwc((long)cmax)));
}
/* Determine the video page segment */
vpage=0;
/* Get the current video mode and save it */
myvmode=gvmode();
/* Put the system in the proper video mode */
svmode(vmode);
/* Clear accumulators */
*iters=0L;
acttime[0]=acttime[1]=acttime[2]=0;
/* Do the benchmark */
do {
start_timer();
/*
** This version modified to run 20 loops of the benchmark
** with each call to random_text 4/14/93 RG
*/
random_text(rcseg,attseg,n,vpage);
stop_timer(eltime);
accumtime(eltime,acttime);
*iters+=20L; /* Bump iterations */
svmode(vmode); /* Clear the screen */
} while(acttime[2]<dotime);
/* Return the system to original mode */
svmode(myvmode);
return;
}
/****************************
* tscroll *
*****************************
* Text scrolling benchmark
*/
tscroll(dotime,n,avgips)
unsigned int dotime; /* # of seconds to do each test */
unsigned int n; /* # of characters to display */
double *avgips; /* average iterations for modes */
{
/* Maximum column # */
unsigned int acttime[3][3]; /* Actual elapsed time */
unsigned long iters[3]; /* Iterations */
unsigned int cmax[3]={80,80,80};
unsigned int modes[3]={2,3,7};
unsigned int nummodes;
unsigned int rcseg; /* Row/column/attr segment */
unsigned int i,j; /* Indices */
unsigned int mytime[3];
/* set modes according to type */
switch(machine_config.graphics_type){
case MDA:
case HERC:
nummodes=1;
modes[0]=7;
break;
case CGA:
nummodes=2;
break;
case EGAM:
case EGAC:
case VGA:
nummodes=3;
break;
}
/* Clear all the accumulators */
for(i=0;i<3;i++)
{ iters[i]=0L;
for(j=0;j<3;j++)
acttime[i][j]=0;
}
/* Allocate memory for the row/column,attribute segments */
if(allocmem(n*3/8+1,&rcseg)!=-1) return;
/* Restart the random number generator */
randnum(1L);
/* Loop through the tests */
for(i=0;i<nummodes;i++)
{
scrolloop(dotime,n,mytime,&iters[i],modes[i],cmax[i],rcseg);
acttime[i][0]=mytime[0];
acttime[i][1]=mytime[1];
acttime[i][2]=mytime[2];
}
/* Clean up after yourself */
freemem(rcseg);
/* calculate avgips */
*avgips=0;
for(i=0;i<nummodes;i++){
*avgips+=(double)iters[i]/timetodouble(acttime[i]);
}
*avgips/=nummodes;
return;
}
/****************************
* scrolloop *
*****************************
* Inner loop for the text scroll benchmark.
*/
scrolloop(dotime,n,acttime,iters,vmode,cmax,rcseg)
unsigned int dotime; /* Max seconds to execute */
unsigned int n; /* Size of rcseg array */
unsigned int acttime[3]; /* Actual elapsed time */
unsigned long *iters; /* Iterations completed */
unsigned int vmode; /* Video mode */
unsigned int cmax; /* Column max */
unsigned int rcseg; /* Row/column/attribute segment */
{
unsigned int vpage; /* Video page */
unsigned int far *rcsptr; /* Pointer to row/column segment */
unsigned int eltime[3]; /* Local for elapsed time */
unsigned int i,j; /* Indices */
unsigned int myvmode; /* Local for current video mode */
unsigned int ulr,ulc,lrr,lrc; /* Corner coordinates for window */
/* just for looks */
printf("Running scroll benchmark ...");
/* Build the row/column/attributes array */
rcsptr=MK_FP(rcseg,0);
for(i=0;i<n;i++)
{
j=3*i;
ulr=(unsigned int)abs(randwc(24L));
ulc=(unsigned int)abs(randwc((long)(cmax-1)));
lrr=ulr+(unsigned int)abs(randwc(24L-(long)ulr));
lrc=ulc+(unsigned int)abs(randwc((long)(cmax-ulc-1)));
*(rcsptr+j)=(ulr<<8)+ulc;
*(rcsptr+j+1)=(lrr<<8)+lrc;
lrc=(unsigned int)abs(randwc(256L)); /* Attributes */
ulc=(unsigned int)abs(randwc((long)(lrr-ulr+1)));
*(rcsptr+j+2)=(lrc<<8)+ulc;
}
/* Set video page */
vpage=0;
/* Get the current video mode */
myvmode=gvmode();
/* Put the system in the proper video mode */
svmode(vmode);
/* Clear the accumulators */
*iters=0L;
acttime[0]=acttime[1]=acttime[2]=0;
/* Do the benchmark */
do {
start_timer();
/*
** This version modified to perform 20 iterations with each
** call to scroll_text. 4/14/93 RG
*/
scroll_text(rcseg,n>>1,vpage);
stop_timer(eltime);
svmode(vmode); /* Clear display */
*iters+=20L; /* Bump iterations */
accumtime(eltime,acttime);
} while(acttime[2]<dotime);
/* Return system to original mode */
svmode(myvmode);
return;
}
/****************************
* graph_bench *
*****************************
** Do the graphics filled-circle benchmark.
** The results array is a 2-dimensional array that has the following
** format:
** results[i][j] i -> picks a group
** j -> picks member of group.
** Each group is 5 elements big.
** results[i][0] = mode
** results[i][1]= # iterations completed
** results[i][2]= microseconds elapsed
** results[i][3]= milliseconds elapsed
** retuslt[i][4]= seconds elapsed
*/
graph_bench(dotime, avgips)
unsigned int dotime; /* Max seconds for each test */
double *avgips;
{
unsigned long results[11][5]; /* Results array */
unsigned int rcvert[3]; /* For converting results */
int i,j; /* Indices */
int gatype; /* Graphics adaptor type */
int mvector[11]; /* Mode vector */
int nmodes; /* Number of modes in vector */
int cx,cy; /* Center of circle */
int color; /* Foreground color */
unsigned int esseg; /* Graphics segment */
unsigned int floodseg; /* Segment for flood routine */
unsigned int acttime[3]; /* Time accumulator */
unsigned int eltime[3]; /* Elapsed time per loop */
unsigned long iters; /* Iterations */
int mymode; /* Storage for current mode */
union REGS myregs;
struct SREGS mysregs;
/* Clear results array */
for(i=0;i<11;i++)
for(j=0;j<5;j++)
results[i][j]=0;
/* Allocate memory for the flood segment (16K should be more
** than enough) */
if(allocmem(1024,&floodseg)!=-1) return;
/* Determine what type of graphics adaptor we've got. */
if((gatype=machine_config.graphics_type)==0) {
*avgips=0;
return;
}
/* Load up the modes vector */
build_mvector(gatype,&nmodes,mvector);
if(nmodes==0){
*avgips=0;
return;
}
/* Loop through each of the modes in the vector */
for(i=0;i<nmodes;i++)
{
mymode=gvmode(); /* Get current mode */
acttime[0]=acttime[1]=acttime[2]=0; /* Clear acc. time */
iters=0L;
setup_circle(mvector[i],&cx,&cy,&color,&esseg);
do {
svmode(mvector[i]);
/* If graphics mode 4, set pallette */
if(mvector[i]==4)
{
myregs.h.ah=0x0B;
myregs.x.bx=257;
intdosx(&myregs,&myregs,&mysregs);
}
start_timer();
circle_fill(cx,cy,color,mvector[i],floodseg,esseg);
stop_timer(eltime);
accumtime(eltime,acttime);
iters++;
} while(acttime[2]<dotime);
svmode(mymode); /* Restore mode */
/* Put results into results array */
results[i][0]=mvector[i]; /* Mode */
results[i][1]=iters; /* Iterations */
results[i][2]=acttime[0]; /* Microseconds */
results[i][3]=acttime[1]; /* Milliseconds */
results[i][4]=acttime[2]; /* Seconds */
}
/* All done, release the flood segment */
freemem(floodseg);
/* calculate avgips */
*avgips=0;
for(i=0;i<nmodes;i++){
rcvert[1]=(unsigned int)(results[i][2] & 0x0FFFFL);
rcvert[2]=(unsigned int)(results[i][3] & 0x0FFFFL);
rcvert[3]=(unsigned int)(results[i][4] & 0x0FFFFL);
*avgips=*avgips+(double)results[i][1]/timetodouble(rcvert);
}
*avgips/=nmodes;
return;
}
/****************************
* circle_fill *
*****************************
* Performs the circle fill algorithm.
*/
circle_fill(cx,cy,color,mode,floodseg,esseg)
int cx,cy; /* Coordinates of center */
int color; /* Foreground color */
int mode; /* Graphics mode */
unsigned int floodseg; /* Segment for flood stack */
unsigned int esseg; /* Grahics segment */
{
int radius; /* Circle radius */
int i; /* Index */
radius=8; /* Starting radius */
/* Draw an initial circle */
draw_circle(cx,cy,radius,color,mode,esseg);
/* Draw and fill the rest */
for(i=0;i<NUMCIRC;++i) {
radius+=8;
draw_circle(cx,cy,radius,color,mode,esseg);
do_flood(cx+radius-4,cy,color,mode,floodseg,esseg);
}
return;
}
/****************************
* setup_circle *
*****************************
* Setup variables needed to draw a circle.
*/
setup_circle(mode,cx,cy,color,esseg)
int mode; /* Grahics mode */
int *cx,*cy; /* Center of circle (returned) */
int *color; /* Color (returned) */
unsigned int *esseg; /* ES segment for drawing (returned) */
{
switch(mode) {
case 4:
case 5: *cx=160;
*cy=100;
*color=3;
*esseg=0xB800;
return;
case 6: *cx=320;
*cy=100;
*color=1;
*esseg=0xB800;
return;
case 13:
*cx=160;
*cy=100;
*color=7;
*esseg=0xA000;
return;
case 14:
*cx=320;
*cy=100;
*color=15;
*esseg=0xA000;
return;
case 15:
*cx=320;
*cy=175;
*color=1;
*esseg=0xA000;
return;
case 16:
*cx=320;
*cy=175;
*color=3;
*esseg=0xA000;
return;
case 17:
case 18:
*cx=320;
*cy=240;
*color= (mode==17) ? 1 : 15;
*esseg=0xA000;
return;
case 19:
*cx=160;
*cy=100;
*color=15;
*esseg=0xA000;
return;
case 255:
*cx=360;
*cy=174;
*color=1;
*esseg=0xB000;
return;
}
}
/****************************
* build_mvector *
*****************************
** Builds a mode vector.
** Pass in a graphics adaptor type, this routine returns a vector
** of video modes that the adaptor can support.
*/
build_mvector(gatype,n,vector)
int gatype; /* Graphics adaptor type */
int *n; /* Returned length of vector */
int vector[]; /* Vector of supported modes */
{
int i; /* Index */
switch(gatype) {
case 0: /* NO graphics adaptor! */
*n=0;
return;
case 1: /* VGA */
vector[0]=4; vector[1]=5; vector[2]=6;
vector[3]=13; vector[4]=14; vector[5]=15;
vector[6]=16; vector[7]=17;vector[8]=18;
vector[9]=19;
*n=10;
return;
case 2: /* EGA enhanced */
vector[0]=4; vector[1]=5; vector[2]=6;
vector[3]=13; vector[4]=14;
vector[5]=16;
*n=6;
return;
case 3: /* CGA */
vector[0]=4; vector[1]=5; vector[2]=6;
*n=3;
return;
case 4: /* EGA monochrome */
vector[0]=6; vector[1]=15;
*n=2;
return;
case 5: /* Hercules */
vector[0]=255;
*n=1;
return;
case 6: /* MDA */
default:
*n=0;
return;
}
}
/****************************
* do_fileio *
*****************************
* Performs the file i/o benchmark.
*/
do_fileio(winptr,dotime,rbytes,wbytes,accrtime,accwtime,maxbytes)
win_handle *winptr; /* current window */
unsigned int dotime; /* User-selected time */
unsigned long *rbytes; /* Total bytes read */
unsigned long *wbytes; /* Total bytes written */
unsigned int accrtime[3]; /* Accumulated read time */
unsigned int accwtime[3]; /* Accumulated write time */
unsigned long maxbytes; /* Maximum bytes avail */
{
unsigned int buffseg; /* Buffer segment for reading/writing */
unsigned int i; /* Index */
char huge *buffptr; /* Pointer to buffer */
unsigned long mymax; /* My accumulated maximum */
/* Clear all the results */
*rbytes=0L;
*wbytes=0L;
accrtime[0]=accrtime[1]=accrtime[2]=0;
accwtime[0]=accwtime[1]=accwtime[2]=0;
/* Allocate a buffer segment (if you can) */
if(allocmem(2500+1,&buffseg)!=-1) return;
buffptr=(char huge *) MK_FP(buffseg,0);
/* Fill up the memory segment */
for(i=0;i<40000;i++)
*buffptr++='A';
/* Initialize maximum */
mymax=0L;
/* Create the files */
for (i=0;i<20;i++)
kreate(i,buffseg,&mymax);
/* Extend them */
for(i=0;i<20;i++)
appnd(i,buffseg,&mymax);
randnum(1L);
/* Do random i/o */
random_fio(winptr,dotime,buffseg,rbytes,wbytes,accrtime,accwtime,
maxbytes,&mymax);
/* Clean up after yourself */
freemem(buffseg);
for(i=0;i<20;i++)
remove(gfname(i));
return;
}
/****************************
* kreate *
*****************************
* Create file n. Write the assigned number of bytes to
* the file and close it. Accumulate the number of bytes
* written and the aggregate time.
*/
kreate(n,buffseg,mymax)
int n; /* File number */
unsigned int buffseg; /* Pointer to buffer segment */
unsigned long *mymax; /* Bytes written */
{
int fh; /* File handle */
unsigned int nb; /* # of bytes to write */
unsigned int wvector[20]={4000,1000,500,2800,2500,
1400,8000,8800,300,21111,
2000,6000,200,48800,1300,
9870,3000,2816,8660,127};
/* Open the file */
fh=ll_create(gfname(n));
nb=wvector[n]; /* Number of bytes to write */
ll_seekwrite(fh,0L,0,buffseg,nb); /* Do the write */
*mymax+=(unsigned long)nb; /* Accumulate bytes written */
ll_close(fh); /* Close the file */
return;
}
/****************************
* appnd *
*****************************
* This routine opens file n and appends the appropriate number of
* bytes.
*/
appnd(n,buffseg,mymax)
int n; /* File number */
unsigned int buffseg; /* Buffer segment */
unsigned long *mymax; /* Total bytes written */
{
int fh; /* File handle */
unsigned int nb; /* Number of bytes */
unsigned int wvector[20]={1200,2030,31111,3400,9099,
2075,7000,400,2200,2700,
2360,1495,5960,3430,70,
3600,8900,1233,4000,1000};
fh=ll_open(gfname(n)); /* Open the file */
nb=wvector[n]; /* Number of bytes to write */
ll_seekwrite(fh,0L,2,buffseg,nb); /* Do the write */
*mymax+=(unsigned long)nb; /* Accumulate bytes written */
ll_close(fh); /* Close the file */
return;
}
/****************************
* random_fio *
*****************************
* This is the random i/o portion of the file i/o benchmark.
* The routine randomly selects, reads, and writes the 20
* files. The system continues the testing until the aggregate
* time (read and write) exceed the selected time (dotime)
*/
random_fio(winptr, dotime,buffseg,rbytes,wbytes,accrtime,accwtime,
maxbytes,mymax)
win_handle *winptr; /* current window */
unsigned int dotime; /* User selected time */
unsigned int buffseg; /* Read/write buffer segment */
unsigned long *wbytes; /* Total bytes written */
unsigned long *rbytes; /* Total bytes read */
unsigned int accwtime[3]; /* Total write-time */
unsigned int accrtime[3]; /* Total read-time */
unsigned long maxbytes; /* Max space avail. */
unsigned long *mymax;
{
int fh; /* File handle */
unsigned long offset; /* Byte offset */
unsigned long flen; /* File length */
unsigned int eltime[3]; /* Elapsed time */
unsigned int nb; /* Number of bytes */
int n; /* File number */
int i; /* Loop index */
unsigned long avg; /* Avg. bytes read per loop */
do {
avg=0L; /* Clear averaging var. */
/* For each pass, do 3 reads and 1 write */
for(i=0;i<3;i++)
{
n=(int)abs(randwc(20L));
fh=ll_open(gfname(n));
flen=ll_filelen(fh); /* Get file length */
offset=abs(randwc(flen)); /* Get random offset */
flen=flen-offset;
if(flen==0L) ++flen;
nb=(flen>32000L) ? 32000 : (unsigned int)flen;
nb=(unsigned int)abs(randwc((unsigned long)nb));
start_timer(); /* Start timing */
ll_seekread(fh,offset,0,buffseg,nb);
stop_timer(eltime);
accumtime(eltime,accrtime);
*rbytes+=(unsigned long)nb;
avg+=(unsigned long)nb;
ll_close(fh);
}
n=(int)abs(randwc(20L)); /* No resonance */
n=(int)abs(randwc(20L)); /* Pick file */
fh=ll_open(gfname(n));
flen=ll_filelen(fh); /* Get file length */
offset=abs(randwc(flen)); /* Get random offset */
nb=(unsigned int)(avg/3L);
if((offset+(unsigned long)nb)>flen)
{ *mymax+=((offset+(unsigned long)nb)-flen);
if(*mymax>maxbytes) return;
}
start_timer(); /* Start timing */
ll_seekwrite(fh,offset,0,buffseg,nb); /* Do the write */
stop_timer(eltime); /* Done timing */
accumtime(eltime,accwtime);
*wbytes+=(unsigned long)nb;
ll_close(fh);
if(winptr!=NULL)
adjust_bar(winptr, accrtime[2]+accwtime[2], dotime); /* bar */
} while(accrtime[2]+accwtime[2]<dotime);
return;
}
/****************************
* gfname *
*****************************
** For file i/o routines. Pass this guy and integer between
** 0 and 19 and he returns a pointer to a null-terminated string
** holding the file's name.
*/
char *gfname(n)
int n; /* Selection number */
{
static char fname[20]; /* File name buffer */
/* Build the name */
strcpy(fname,"BYTEDAT.");
itoa(n,fname+8,10);
return(fname);
}
/****************************
* ll_diskseek *
*****************************
** Low level disk seek benchmark (hard disks)
** NOTE: This test requires that the throughput test be already
** run so that bytes per second is available.
*/
ll_diskseek(drive,bytespersec,seektime)
unsigned int drive; /* Drive number (0=1st hard disk) */
double bytespersec; /* Bytes per sec from throughput test */
double *seektime; /* Avg seek time */
{
unsigned int buffseg; /* Buffer segment */
harddiskspecs myhdisk; /* Hard disk specs */
unsigned int mytime[3]; /* Local for elapsed time */
unsigned int i; /* Index */
double divisor;
double transtime;
double thistime;
/* Allocate memory segments for the arrays */
if(allocmem(512/16+1,&buffseg)!=-1)
return;
/* Determine the drive's maximum cylinder number */
if(get_hdinfo(drive+0x80,&myhdisk)==0)
{ freemem(buffseg);
return;
}
divisor=(long)myhdisk.maxcyl*(long)(myhdisk.maxcyl-1);
transtime=(double)512.0/bytespersec;
drive +=0x80; /* Hard disk */
for(i=1;i<myhdisk.maxcyl;i++)
{ hd_1seek(drive,0,buffseg); /* Seek to 0 */
start_timer();
hd_1seek(drive,i,buffseg); /* Seek distance=i */
stop_timer(mytime);
thistime=timetodouble(mytime); /* Get time */
thistime-=transtime; /* Subtract transfer time */
thistime=thistime*((double)(myhdisk.maxcyl-i)/(double)divisor);
*(seektime)+=thistime+thistime; /* Times 2 */
}
/* Free memory segments */
freemem(buffseg);
return;
}
/****************************
* ll_hdthru *
*****************************
** Low level hard disk read throughput.
*/
ll_hdthru(drive,n,bpersec)
unsigned int drive; /* Drive to test */
unsigned int n; /* # of iterations to test */
double *bpersec; /* Bytes per second transfer */
{
unsigned int cysecarrseg; /* Cylinder/array segment */
unsigned int buffseg; /* Buffer segment */
harddiskspecs myhdisk; /* Hard disk specs */
unsigned int far *cysecptr; /* Far pointer to cyl/sect array */
unsigned int eltime[3]; /* Local for elapsed time */
unsigned int seektime1[3];
unsigned int seektime2[3];
unsigned int cyl; /* Cylinder */
unsigned int sect; /* Sector */
unsigned long totbytes; /* Total bytes */
unsigned int i; /* Index */
/* Clear return value */
*bpersec=0.0;
/* Determine the configuration of the hard disk */
if(get_hdinfo(drive+0x80,&myhdisk)==0)
return;
/* Build the cylinder/sector and # of sectors arrays */
if(allocmem(n/4+1,&cysecarrseg)!=-1)
return;
cysecptr=MK_FP(cysecarrseg,0); /* Make a pointer */
if(allocmem((myhdisk.sectspertrack*512)/16+1,&buffseg)!=-1)
{ freemem(cysecarrseg);
return;
}
/* Build arrays for first test */
randnum(1L);
i=0;
totbytes=0L;
do {
cyl=abs((int)randwc((unsigned long)myhdisk.maxcyl));
sect=abs((int)randwc((unsigned long)myhdisk.sectspertrack))+1;
*(cysecptr+i)=(sect&0x3f)+((cyl&255)<<8)+((cyl&0x300)>>2);
++i;
*(cysecptr+i)=myhdisk.sectspertrack-sect+1;
totbytes+=(unsigned long)*(cysecptr+i);
} while(++i<((n*2)-1));
totbytes=(totbytes-(unsigned long)n)*512L; /* FIX!!! */
/* Do first test */
seektime1[0]=seektime1[1]=seektime1[2]=0;
start_timer();
i=hd_rread(drive+0x80,cysecarrseg,buffseg,n);
stop_timer(eltime);
if(i!=0) printf("Whoops at %d\n",i);
accumtime(eltime,seektime1);
/* Fix up array for second test */
for(i=0;i<n;i++)
*(cysecptr+2*i+1)=1;
/* Do second test */
seektime2[0]=seektime2[1]=seektime2[2]=0;
start_timer();
i=hd_rread(drive+0x80,cysecarrseg,buffseg,n);
stop_timer(eltime);
if(i!=0) printf("2Whoops at %d\n",i);
accumtime(eltime,seektime2);
/* Calculate bytes per second */
*bpersec=(double)totbytes/(timetodouble(seektime1)-timetodouble(seektime2));
/* Close it up */
freemem(cysecarrseg);
freemem(buffseg);
return;
}
/****************************
* get_hdinfo *
*****************************
** Return hard disk information.
** Call with:
** drive = hard disk number (0x80 is first drive, 0x81 is second)
** Returns:
** hdinf structure filled with disk information
** return value is number of drives connected to first
** controller
*/
int get_hdinfo(drive,hdinf)
unsigned int drive; /* Drive to get information on */
harddiskspecs *hdinf; /* Structure of hard disk info */
{
union REGS inregs, outregs; /* For talking to the BIOS */
/* Make the call to INT 13H */
inregs.h.ah=8;
inregs.h.dl=drive;
int86(0x13,&inregs,&outregs);
/* Pass back results */
hdinf->maxhead=outregs.h.dh;
hdinf->maxcyl=outregs.h.ch + ((outregs.h.cl & 0xC0)<<2);
hdinf->sectspertrack=outregs.h.cl & 0x3F;
/* Return number of attached drives */
return((int)outregs.h.dl);
}
/****************************
* segcopy *
*****************************
* Given two segments, copies n bytes from source to
* destination.
*/
segcopy(destin,source,n)
unsigned int destin; /* Destination segment */
unsigned int source; /* Source segment */
unsigned int n; /* Number of bytes */
{
char huge *dptr;
char huge *sptr;
/* Make some far pointers */
dptr=MK_FP(destin,0);
sptr=MK_FP(source,0);
do {
*dptr++=*sptr++;
} while(--n);
}
/****************************
* rload_int_seg *
*****************************
** Load a segment with random integers.
** Call with:
** rload_int_seg(segptr,n,max)
** Where:
** segptr = unsigned integer holding the segment
** n = number of elements to load the array
** max = maximum value (must be unsigned)
*/
rload_int_seg(segptr,n,max)
unsigned int segptr;
unsigned int n;
int max;
{
int huge *mysegptr; /* For coercion */
unsigned int i; /* Index */
/* Set up my pointer */
mysegptr=MK_FP(segptr,0);
/* Loop and load the array */
for(i=0;i<n;i++)
*mysegptr++=(int)randwc((long)max);
}
/****************************
* accumtime() *
*****************************
** Accumulate elapsed time.
** Call with:
** accumtime(eltime,tottime)
** Where:
** eltime[3] = array of elapsed time to be added to
** tottime
** Returns:
** tottime[3] = total time
*/
accumtime(eltime,tottime)
unsigned int eltime[3]; /* Elapsed time */
unsigned int tottime[3]; /* Total time */
{
/* Add in microseconds */
tottime[0]+=eltime[0];
/* Handle overflow */
while(tottime[0]>=1000)
{ tottime[0]-=1000;
tottime[1]+=1;
}
/* Add in milliseconds */
tottime[1]+=eltime[1];
/* Handle overflow */
while(tottime[1]>=1000)
{ tottime[1]-=1000;
tottime[2]+=1;
}
/* Add in seconds */
tottime[2]+=eltime[2];
}
/****************************
* randwc() *
*****************************
** Returns random modulo num.
*/
long randwc(num)
long num;
{
return(randnum(0L)%num);
}
/****************************
* randnum() *
*****************************
** Second order linear congruential generator.
** Constants suggested by J. G. Skellam.
** If val==0, returns next member of sequence.
** val!=0, restart generator.
*/
long randnum(lngval)
long lngval;
{
register long interm;
static long randw[2] = { 13L , 117L };
if (lngval!=0L)
{ randw[0]=13L; randw[1]=117L; }
interm=(randw[0]*254754L+randw[1]*529562L)%999563L;
randw[1]=randw[0];
randw[0]=interm;
return(interm);
}
/****************************
* timetodouble *
*****************************
* Convert a time array micro, milli, seconds to a floating-point
* double value.
*/
double timetodouble(histime)
unsigned int histime[3];
{
double temp; /* Local for holding time */
temp=(double)histime[0]; /* Microseconds */
temp=temp/1000.0;
temp+=(double)histime[1]; /* Milliseconds */
temp=temp/1000.0;
temp+=(double)histime[2]; /* Seconds */
return(temp);
}
void adjust_bar(win_handle *winptr, int curr, int tot)
/****************************
** adjust_bar *
*****************************
**
**
** Colors the sliding bar graph
*/
{
double curlen;
int i;
curlen = ((double)curr/tot)*20;
curlen=(curlen>20) ? 20: curlen;
for(i=oldlen;i< (int) curlen;i++){
winputch(winptr, 39+i, 23, 0xb2);
if (tdef[13])
click();
}
chattr(winptr, 39, 23, (int) curlen, 1, WHITE, RED);
oldlen=curlen;
return;
}